
import AnimationComponent from "./AnimationComponent";
import { BuffManager } from "./BuffManager";
import { GridMap } from "./findpath/Grid";
import GameWorld from "./GameWorld";
import MoveComponent from "./MoveComponent";
import { Skill } from "./Skill";
import UnitStateMachine, { UnitStateEnum } from "./UnitStateMachine";
import UnitView from "./view/UnitView";
import {UnitConfig} from "../config/unit"
import { IReference, ObjectPool } from "../base/ObjectPool";
import ResManager from "../manager/ResManager";
export default class Unit extends IReference {

    public groupId: number;
    public unitId: number;
    public world: GameWorld = null;

    public moveComponent: MoveComponent = null;
    public anim: AnimationComponent = null;
    public buffManager: BuffManager = null;
    public fsm: UnitStateMachine = null;
    public skills: Skill[] = [];

    public speed = 2;
    public get pos() {
        return this._pos;
    }
    public set pos(pos: cc.Vec2) {
        this._pos = pos;
        this.node.zIndex = -Math.round(this.pos.y);
        this.node.position = cc.v3(pos.mul(this.world.gridEdge));
    }
    public set direction(dir: cc.Vec2) {
        this._direction = dir;
        this.anim.switchDirection(dir);
    }
    public get direction() {
        return this._direction;
    }
    public gridPos:cc.Vec2 =  new cc.Vec2();
    public node: cc.Node = null;
    private unitData = null;
    private unitView: UnitView = null;
    private _pos: cc.Vec2 = new cc.Vec2();
    private _direction: cc.Vec2 = new cc.Vec2();

    private isdeath: boolean = false;
    public static creat(unitId, groupId, world: GameWorld,pos?,direction?): Unit {
        let unit = ObjectPool.instance.get(Unit) as Unit;
        if (!unit) {
            unit = new Unit();
            unit.unitId = unitId;
            unit.unitData = {};
            for (const key in UnitConfig[unitId]) {
                unit.unitData[key] = UnitConfig[unitId][key];
            }
            unit.unitData.currentHp = unit.unitData.maxhp;
            let node = ResManager.instance.loadPrefabAsync('model/unit');
            unit.node = node;
            unit.unitView = unit.node.getComponent(UnitView);
            let isPlayer = groupId ==world.selfGroupId;
            unit.unitView.init(unit.unitData,isPlayer);
            new MoveComponent(unit);
            new AnimationComponent(unit);
            new BuffManager(unit);
            new UnitStateMachine(unit);
            unit.groupId = groupId;
            unit.world = world;
            unit.node.parent = world.mapNode;
            if (pos) {
                unit.pos = pos;
                unit.gridPos = pos;
            }
            unit.anim.play('S');
            if (direction) {
                unit.direction = direction;
            }else{
                unit.direction = cc.v2(0,1);
            }
            GridMap.instance.getNode(unit.pos.x,unit.pos.y).hasUnit = true;
        }
        return unit;
    }
    public getProperty(id: string | number) {
        return this.unitData[id];
    }
    public resetProperty(id: string | number, value, method: number) {
        if (this.isDeath()) {
            return;
        }
        if (method == 0) {
            this.unitData[id] = value;
        } else if (method == 1) {
            this.unitData[id] = this.unitData[id] + value;
        } else {
            this.unitData[id] = this.unitData[id] - value;
        }
        this.unitView.change(id);

        if (this.unitData) {
            if (this.unitData['currentHp'] <= 0) {
                this.isdeath = true;
                this.changeState(UnitStateEnum.Death);
                //this.clear();
            }
        }

    }
    public changeState(stateName: string, ...args) {
        this.fsm.changeState(stateName, ...args);
    }
    public clear() {
        this.world.removeUint(this);
        GridMap.instance.getNode(this.gridPos.x,this.gridPos.y).hasUnit = false;
        this.node.removeFromParent();
        this.anim.clear();
        this.buffManager.clear();
        this.moveComponent.canelMove();
        this.fsm.stop();
        ObjectPool.instance.put(Unit, this);
    }

    public isDeath() {
        return this.isdeath;
    }
    public update(dt) {

        this.fsm.update(dt);
        this.skills.forEach((skill) => { skill.update(dt) });
        this.buffManager.update(dt);
    }
}
